package com.tvunetworks.center.user.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.tvunetworks.center.common.constant.LocalConstant;
import com.tvunetworks.center.gs.model.Device;
import com.tvunetworks.center.user.mapper.UserDeviceMapper;
import com.tvunetworks.center.user.service.DeviceService;
import com.tvunetworks.center.user.util.MemcacheUtil;
import lombok.extern.slf4j.Slf4j;
import net.spy.memcached.MemcachedClient;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @program: tvucc-user
 * @description: DeviceServiceImpl
 * @author lebronchen
 * @create: 2020-03-09 14:51
 **/
@Service
@Slf4j
public class DeviceServiceImpl implements DeviceService {

    private static final String STATUS_FOR_GRIDWITCH = "status_for_gridwitch_";

    @Autowired
    @Qualifier("tpdsMemcacheClient")
    private MemcachedClient tpdsMemcacheClient;
    @Autowired
    private UserDeviceMapper userDeviceMapper;
    @Autowired
    private MemcacheUtil memcacheUtil;


    @Override
    public Device getMemDevice(String peerId) {
        if (StringUtils.isEmpty(peerId)) {
            return null;
        }
        if (peerId.length() > 32) {
            log.error("DeviceServiceImpl getMemDevice peerId size error peerId:{}", peerId);
            return null;
        }
        return (Device) tpdsMemcacheClient.get(STATUS_FOR_GRIDWITCH + peerId);
    }

    @Override
    public Device getCurrentDevice(String peerId) {
        if (StringUtils.isBlank(peerId)) {
            return null;
        }
        Device memDevice = this.getMemDevice(peerId.toLowerCase());
        if (memDevice != null) {
            if (LocalConstant.DeviceStatus.ONLINE.equals(memDevice.getStatus()) || LocalConstant.DeviceStatus.OFFLINE.equals(memDevice.getStatus())) {
                memDevice.setLivePeerId(null);
                memDevice.setLivePeerName(null);
            }
            if (StringUtils.isNotBlank(memDevice.getPlatform())) {
                memDevice.setPlatform(memDevice.getPlatform().trim());
            }
            return memDevice;
        }
        Device dbDevice = this.getDevice(peerId.toLowerCase());
        if (dbDevice == null) {
            return null;
        }
        dbDevice.setStatus(LocalConstant.DeviceStatus.OFFLINE);
        dbDevice.setLivePeerId(null);
        dbDevice.setLivePeerName(null);
        if (StringUtils.isNotBlank(dbDevice.getPlatform())) {
            dbDevice.setPlatform(dbDevice.getPlatform().trim());
        }

        if (LocalConstant.DeviceStatus.LIVING.equals(dbDevice.getStatus())
                && StringUtils.isNotBlank(dbDevice.getLivePeerId())
                && StringUtils.isBlank(dbDevice.getLivePeerName())) {
            Device d = this.getCurrentDevice(dbDevice.getLivePeerId());
            if (d != null) {
                dbDevice.setLivePeerName(d.getName());
            }
        }

        return dbDevice;
    }

    @Override
    public List<Device> listCurrentDevice(Collection<String> peerIds) {
        if (CollectionUtils.isEmpty(peerIds)) {
            return null;
        }

        // 通过 Set 去重
        HashSet<String> peerIdSet = new HashSet<>();
        for (String peerId : peerIds) {
            peerIdSet.add(peerId.toLowerCase());
        }

        Set<String> illegalPids = peerIdSet.stream().filter(e -> e.length() > 32).collect(Collectors.toSet());
        if (!CollectionUtils.isEmpty(illegalPids)) {
            log.error("DeviceServiceImpl listCurrentDevice peerId size error illegalPids:{}", illegalPids);
            peerIdSet.removeAll(illegalPids);
        }

        if (CollectionUtils.isEmpty(peerIdSet)) {
            return null;
        }

        // 封装查询 memcache 的 key
        HashSet<String> memcacheKeys = new HashSet<>();
        for (String peerId : peerIdSet) {
            memcacheKeys.add(STATUS_FOR_GRIDWITCH + peerId.toLowerCase());
        }

        // 记录 memcache 中查询到的 peerId
        Set<String> inMemPeerIds = new HashSet<>();
        // 记录结果
        List<Device> resultList = new ArrayList<>();

        Map<String, Object> bulkMap = memcacheUtil.multiGet(tpdsMemcacheClient, memcacheKeys);
        if (!CollectionUtils.isEmpty(bulkMap)) {
            Collection<Object> values = bulkMap.values();
            for (Object o : values) {
                Device d = (Device) o;
                resultList.add(d);
                if("83cca10aa0972b150000000000000002".equals(d.getPeerId().toLowerCase())){
                    log.error("83cca10aa0972b150000000000000002 info from cache==="+ JSONObject.toJSONString(d));
                }
                inMemPeerIds.add(d.getPeerId());
            }
        }

        // 移除掉 memcache 中查询到的 peerId，得到需要查询 DB 的 peerIds
        peerIdSet.removeAll(inMemPeerIds);

        if (!CollectionUtils.isEmpty(peerIdSet)) {
            List<Device> dbList = userDeviceMapper.listDevice(peerIdSet, null);
            if (!CollectionUtils.isEmpty(dbList)) {
                for (Device dbDevice : dbList) {
                    if("83cca10aa0972b150000000000000002".equals(dbDevice.getPeerId().toLowerCase())){
                        log.error("83cca10aa0972b150000000000000002 info FROM db==="+ JSONObject.toJSONString(dbDevice));
                    }
                    dbDevice.setStatus(LocalConstant.DeviceStatus.OFFLINE);
                    dbDevice.setLivePeerId(null);
                    dbDevice.setLivePeerName(null);
                    if (StringUtils.isNotBlank(dbDevice.getPlatform())) {
                        dbDevice.setPlatform(dbDevice.getPlatform().trim());
                    }
                }
                resultList.addAll(dbList);
            }
        }

        for (Device device : resultList) {
            if (LocalConstant.DeviceStatus.LIVING.equals(device.getStatus())
                    && StringUtils.isNotBlank(device.getLivePeerId())
                    && StringUtils.isBlank(device.getLivePeerName())) {
                Device d = this.getCurrentDevice(device.getLivePeerId());
                if (d != null) {
                    device.setLivePeerName(d.getName());
                }
            }
        }

        return resultList;
    }

    @Override
    public List<Device> listCurrentDevice(Collection<String> peerIds, String condition) {
        List<Device> devices = this.listCurrentDevice(peerIds);
        if (CollectionUtils.isEmpty(devices) || StringUtils.isEmpty(condition)) {
            return devices;
        }

        devices = devices.stream().filter(device -> StringUtils.containsIgnoreCase(device.getPeerId(), condition) || StringUtils.containsIgnoreCase(device.getName(), condition) || StringUtils.containsIgnoreCase(device.getRemark(), condition)).collect(Collectors.toList());
        return devices;
    }

    @Override
    public List<String> checkDeviceType(Collection<String> peerIds, String deviceType) {
        List<String> result = new ArrayList<>();
        if (CollectionUtils.isEmpty(peerIds) || StringUtils.isEmpty(deviceType)) {
            return result;
        }
        Set<String> peerIdSet = peerIds.stream().filter(s -> s.length() <= 32).map(String::toLowerCase)
                .collect(Collectors.toSet());
        if (CollectionUtils.isEmpty(peerIdSet)) {
            log.error("DeviceServiceImpl>>>>>>checkDeviceType>>>>>>all peerId size error illegal.peerIds:[]}]", peerIds);
            return result;
        }
        // 封装查询 memCache 的 key
        HashSet<String> memCacheKeys = new HashSet<>();
        peerIdSet.forEach(s-> memCacheKeys.add(STATUS_FOR_GRIDWITCH + s));
        Map<String, Object> bulkMap = memcacheUtil.multiGet(tpdsMemcacheClient, memCacheKeys);
        if (bulkMap != null && bulkMap.size() > 0) {
            result.addAll(bulkMap.values().stream().filter(s -> {
                Device device = (Device) s;
                peerIdSet.remove(device.getPeerId());
                return deviceType.equalsIgnoreCase(device.getType());
            }).map(s->((Device) s).getPeerId()).collect(Collectors.toSet()));
        }
        if (!CollectionUtils.isEmpty(peerIdSet)) {
            List<Device> dbList = userDeviceMapper.listDevice(peerIdSet, null);
            if (!CollectionUtils.isEmpty(dbList)) {
                result.addAll(dbList.stream().filter(s -> deviceType.equalsIgnoreCase(s.getType()))
                        .map(Device::getPeerId).collect(Collectors.toSet()));
            }
        }
        List<String> peerIdList = new ArrayList<>(peerIds);
        if (!CollectionUtils.isEmpty(result) && result.size() != peerIdList.size()) {
            peerIdList.removeAll(result);
            log.error("DeviceServiceImpl>>>>>>checkDeviceType>>>>>> device type illegal.peerIds:[]}]", peerIdList);
        }
        return result;
    }

    private Device getDevice(String peerId) {
        if (StringUtils.isEmpty(peerId)) {
            return null;
        }
        return userDeviceMapper.getDevice(peerId);
    }
}
